iT邦幫忙

2023 iThome 鐵人賽

DAY 6
0
自我挑戰組

Lex & Yacc 學習筆記系列 第 6

[Day6] Lex - yywrap

  • 分享至 

  • xImage
  •  

本篇內容

  • 介紹yywrap
  • 範例 - 文字計數器

介紹

我們在之前的文章有提到,yywrap是在 yylex() 讀取完成後所呼叫的函式,可以在定義後續程式的執行動作。
我們今天將用以下的範例來說明yywrap的運作方式。

範例 - 文字計數器

Description

給定一篇文章,目標是利用Lex計算出文章的字元數、單詞數與行數。

程式實作

Definitions

在這個範例中,我們需要定義三個全域變數來記錄行數,字數與字元數。

%{
    int yylex(void);
    int nchar, nword, nline; 
%}

Rules

我們針對以下的情況,對相對應的計數器做更新:

  • 當我們讀取到換行符號\n,要將行數+1
  • 當我們讀取到空白符(blank or tab space),要將字數+1,且要將該字的字元數加到字元計數器。
  • 當我們讀到非空白的任何字元,則將字元數+1。
%%

\n          { nline++; nchar++; }
[^ \t\n]+   { nword++, nchar += yyleng; }
.           { nchar++; } 

Subroutines

我們將主程式寫在這裡。
在讀取檔案後,呼叫lex來執行詞語標記。
讀取結束後,印出統計結果。

我們分別在yywrap與主程式的yylex之後分別印出一些文字,看看哪部分會先被執行。

%%

int yywrap(void) {
    printf("Characters: %d\nWords: %d\nLines: %d\n", nchar, nword, nline);
    return 1;
}

int main(void) {
    const char* sFile = "file.txt";
    FILE* fp = fopen(sFile, "r");
    if (fp == NULL) {
        printf("cannot open %s\n", sFile);
        return -1;
    }
    yyin = fp;
    yylex();
    printf("Main function ends here.\n");
    return 0;
}

完整範例

%{
    int yylex(void);
    int nchar, nword, nline; 
%}

%%

\n          { nline++; nchar++; }
[^ \t\n]+   { nword++, nchar += yyleng; }
.           { nchar++; } 

%%

int yywrap(void) {
    printf("Characters: %d\nWords: %d\nLines: %d\n", nchar, nword, nline);
    return 1;
}

int main(void) {
    const char* sFile = "file.txt";
    FILE* fp = fopen(sFile, "r");
    if (fp == NULL) {
        printf("cannot open %s\n", sFile);
        return -1;
    }
    yyin = fp;
    yylex();
    printf("Main function ends here.\n");
    return 0;
}

執行結果

輸入內容

Hello, World!
I am a software engineer.
I like lex and yacc.

輸出結果

Characters: 60
Words: 12     
Lines: 2      
Main function ends here.

答案揭曉:在yylex執行完畢後,會先呼叫yywrap,才接著執行主程式後續的內容。
因此,如果要讀取多個檔案,各檔案的執行流程應該寫在yywrap裡。所有讀取程序完成後的後續步驟則寫在yylex後。

至於如何讀取多個檔案,我們後續會再提到。

💡 由於最後一行沒有換行符號,所以行數統計比實際行數少1行是正常的。

結語

今天我們介紹了yywrap的用法,並且簡單的複習一下從開始到現在的常用lex功能。
我們明天會進入Lex基礎篇的最後一部分 - 錯誤訊息。

參考資料

  • Levine, John R., Tony Mason and Doug Brown [1992]. Lex & Yacc. O’Reilly & Associates, Inc. Sebastopol, California.

上一篇
[Day5] Lex - yyout
下一篇
[Day7] Lex - Error Handling
系列文
Lex & Yacc 學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言